import pickle
import protocol
import logging
import platform
import uuid 
import datetime
    
class ProtocolHandler():
    handlerlist = {}
    last_ping_time = None
    
    
    def __init__(self, connecter):
        self.connecter = connecter
        self.connecter.handle_connect = self.OnConnect
        self.handlerlist[protocol.s2c_ping_request] = self.PingRespond
        self.last_ping_time = datetime.datetime.now()
        self.ping_interval = datetime.timedelta(seconds = 2)
        
    def OnData(self, data):
        protocol = None
        fun = None
        try:
            protocol  = pickle.loads(data)
            fun = self.handlerlist[protocol.id]
        except pickle.PickleError as e:
            self.connecter.close()
            logging.exception(e)
            return
        except Exception as e:
            self.connecter.close()
            logging.exception(e)
            return
        
        fun(protocol)
    
    def PingRespond(self, request):
        pass
    
        
    def DoSend(self, data):
        try:
            data = pickle.dumps(data, pickle.HIGHEST_PROTOCOL)
        except pickle.PickleError as e:
            logging.exception(e)
            return
        self.connecter.pull(data)
        
        
    def RegisterProtocol(self, id, fun):
        if id in self.handlerlist:
            raise ValueError(''.fromat('id {0} has in list', id))

        
        if type(fun) != type(self.OnData):
            raise ValueError('fun need function')
        
        self.handlerlist[id] = fun
        
    def UnregisterProtocol(self, id):
        self.handlerlist.pop(id)
    
    def Loop(self):
        for v in self.connecter.get_recv_data():
            self.OnData(v)
        now =datetime.datetime.now()
        if (now - self.last_ping_time) > self.ping_interval:
            self.last_ping_time = now
            self.DoPingRequest()
            

    def OnConnect(self):
        info = protocol.C2SClientInfo()
        info.bits = platform.architecture()[0]
        info.system = platform.system()
        if info.system == 'Windows':
            info.os = 'Win' + platform.win32_ver()[0]
        elif info.system == 'Linux':
            info.os = platform.linux_distribution()[0]
        
        macaddr = uuid.UUID(int = uuid.getnode())
        info.mac_addr = macaddr.hex[-12:]
        info.name = platform.node()
        self.DoSend(info)
        print(info)
        
    def DoPingRequest(self):
        request = protocol.C2SPingRequest()
        self.DoSend(request)
